<!-- 菜单信息 -->
<template>
  <div class="">
    <el-row :gutter="10">
      <el-col :span="6">
        <el-card class="box-card">
          <el-input placeholder="输入关键字进行过滤" v-model.trim="filterText"></el-input>
          <el-tree
            class="filter-tree"
            :load="loadNode"
            :props="defaultProps"
            :filter-node-method="filterNode"
            :expand-on-click-node="false"
            :current-node-key="currentNodeKey"
            node-key="id"
            :default-expanded-keys="state.defaultExpandedKeys"
            highlight-current
            lazy
            @node-click="handleNodeClick"
            ref="treeRef">
            <template #default="{ node, data }">
              <span class="custom-tree-node">
                <span>{{ node.label }}</span>
                <span>
                  <el-button type="primary" link v-if="node.level !== 5" @click.stop="handleAppend(node, data)">新增</el-button>
                  <el-button link class="red ml0" v-if="node.level !== 1" @click.stop="handleRemove(node, data)">删除</el-button>
                </span>
              </span>
            </template>
          </el-tree>
        </el-card>
      </el-col>
      <el-col :span="18">
        <el-card class="box-card">
          <el-form label-width="120px" :model="menuForm" :rules="rules" :highlight-current="true" v-loading="loading" ref="formRef">
            <el-row :gutter="10">
              <el-col :span="10">
                <el-form-item label="菜单类型：" prop="type">
                  <el-radio-group v-model="menuForm.type" @change="handleChangeMenuType">
                    <el-radio label="1" :value="1">目录</el-radio>
                    <el-radio label="2" :value="2">菜单</el-radio>
                    <el-radio label="3" :value="3">权限</el-radio>
                  </el-radio-group>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="10">
              <el-col :span="7">
                <el-form-item label="标题：" prop="title">
                  <el-input v-model.trim="menuForm.title" placeholder="点击新增后添加标题"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="7">
                <el-form-item label="路由：" prop="path">
                  <el-input v-model.trim="menuForm.path"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="1" v-if="menuForm.type === 1">
                <el-tooltip placement="top" content="目前可随意填写地址,不重复即可（如：1）">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
                <el-col :span="1"> </el-col>
              </el-col>
              <el-col :span="1" v-if="menuForm.type === 2">
                <el-tooltip placement="top" content="前端页面访问的地址（如：/menuInfo）">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
              </el-col>
              <el-col :span="1" v-if="menuForm.type === 3">
                <el-tooltip placement="top" content="后端接口的地址（如：back/auth）">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
              </el-col>
            </el-row>
            <el-row :gutter="10" v-if="menuForm.type === 3">
              <el-col :span="7">
                <el-form-item label="请求方式：" prop="method">
                  <el-select v-model="menuForm.method" placeholder="请选择请求方式" clearable>
                    <el-option v-for="item in selectRequestMethodList" :label="item.dictLabel" :value="item.dictValue" :key="item.id"></el-option>
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="7">
                <el-form-item label="动作：" prop="action">
                  <el-input v-model.trim="menuForm.action"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="1">
                <el-tooltip placement="top" content="按钮对应权限的名称(如：新增:add;编辑:edit)">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
              </el-col>
            </el-row>
            <el-row :gutter="10" v-if="menuForm.type !== 3">
              <el-col :span="7" v-if="menuForm.type === 2">
                <el-form-item label="模块名称：" prop="name">
                  <el-input v-model.trim="menuForm.name"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="7" v-if="menuForm.type === 1">
                <el-form-item label="权重：" prop="sort">
                  <el-input v-model.trim="menuForm.sort"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="7" v-if="[1, 2].includes(menuForm.type)">
                <el-form-item label="图标：" prop="icon">
                  <el-input v-model.trim="menuForm.icon"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="1" v-if="menuForm.type === 2">
                <el-tooltip placement="top" content=" 一级为菜单时需要添加图标">
                  <el-icon class="icon-wzg-config">
                    <InfoFilled />
                  </el-icon>
                </el-tooltip>
              </el-col>
            </el-row>
            <el-row :gutter="10" v-if="menuForm.type === 2">
              <el-col :span="7">
                <el-form-item label="权重：" prop="sort">
                  <el-input v-model.trim="menuForm.sort"></el-input>
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>
          <el-row :gutter="10">
            <el-col :span="6" :offset="1">
              <el-button type="primary" :icon="Check" :disabled="disabledbtn" @click="submitForm">保存</el-button>
              <!-- <el-button type="success"
                         icon="el-icon-refresh"
                         :disabled="disabledbtn"
                         @click="getMenuInfo">刷新</el-button> -->
            </el-col>
          </el-row>
          <el-row :gutter="10">
            <el-col :span="20" :offset="1">
              <ul>
                <li>1.菜单只有一级的时候，路由写真实路由，二级的时候，路由只要不重复即可，数字即可</li>
                <li>2.图标字段填写规则分号分割，前一部分为element图标，后一部分为elementplus图标，如：el-icon-mobile-phone;Iphone</li>
                <li>3.element图标的获取地址：https://element.eleme.cn/#/zh-CN/component/icon</li>
                <li>4.elementplus图标的获取地址：https://element-plus.org/zh-CN/component/icon.html（目前可不写）</li>
              </ul>
            </el-col>
          </el-row>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts" name="menuInfo">
import { ElMessage, ElMessageBox, type TreeInstance, type TreeNodeData } from "element-plus";
import { Check } from "@element-plus/icons-vue";
import { useDictData } from "@/hooks/network/useDictData.js";
import type { IDictData } from "@/types/dict";
import { commonMenuInfo, deleteMenuInfo, getMenuInfo } from "@/utils/api/menu";
import type { postOrPutType } from "@/constants";
import type { IMenuDTO, ISearchMenu } from "@/types/menu";
import type Node from "element-plus/es/components/tree/src/model/node";

const state = reactive({
  defaultExpandedKeys: [0] /* 默认显示哪几级信息 */
});
let { getDictData } = useDictData();
const selectRequestMethodList = ref<Array<IDictData>>([]);
const filterText = ref("");
const treeRef = ref<TreeInstance>();
const formRef = useTemplateRef("formRef");
const defaultProps = reactive({
  children: "items",
  label: "title"
});
const currentNodeKey = ref(""); /* 当前选中的节点 */
const searchCondition = reactive<ISearchMenu>({
  p_id: 0
});
const methodType = ref<postOrPutType>("POST");

const menuForm = reactive<IMenuDTO>({
  id: -1,
  p_id: -1,
  type: 1,
  icon: "",
  title: "",
  path: "",
  name: "",
  method: "",
  action: "",
  sort: 0
});
let rules = ref();
/* 目录规则 */
const contentRules = {
  title: [{ required: true, message: "请填写标题", trigger: "blur" }],
  path: [{ required: true, message: "请填写路由", trigger: "blur" }],
  sort: [{ required: true, message: "请填写权重", trigger: "blur" }]
};

/* 菜单规则 */
const menuRules = {
  title: [{ required: true, message: "请填写标题", trigger: "blur" }],
  name: [{ required: true, message: "请填写模块名称", trigger: "blur" }],
  path: [{ required: true, message: "请填写路由", trigger: "blur" }],
  sort: [{ required: true, message: "请填写权重", trigger: "blur" }]
};
/* 按钮规则 */
const buttonRules = {
  title: [{ required: true, message: "请填写标题", trigger: "blur" }],
  path: [{ required: true, message: "请填写路由", trigger: "blur" }],
  method: [{ required: true, message: "请选择请求方式", trigger: "blur" }],
  action: [{ required: true, message: "请填写行为", trigger: "blur" }]
};
const delVisibleType = ref("delete"); /* 删除类型（单选，多选） */
const loading = ref(false);
const disabledbtn = ref(false); /* 可用与不可用 */
const node_had = ref<Node>();
const isParent = ref(true);
const id = ref(0); /* 选中删除id */

/* 过滤节点信息 */
const filterNode = (value: string, data: TreeNodeData) => {
  if (!value) return true;
  return data.title.indexOf(value) !== -1;
};
/* 更新tree中某个结点 */
const handleUpdateTree = () => {
  // 通过ID利用DOM找到该结点
  const node = treeRef.value?.getNode(node_had.value!.data);
  const tempNode = isParent.value ? node?.parent : node;
  // 更改该结点属性（重要）
  if (tempNode) {
    tempNode.loaded = false;
    // 手动调用该结点数据加载方法
    tempNode.loadData(() => {});
  }
};

/* 点击获取节点信息 */
const handleNodeClick = (data: IMenuDTO, _node: Node) => {
  node_had.value = _node;
  // if (node.value?.level === 1) return;
  isParent.value = true;

  menuForm.id = data.id;
  menuForm.title = data.title;
  menuForm.p_id = _node.parent.data.id;
  if (data.id !== -1) {
    /* 修改 */
    methodType.value = "PUT";

    menuForm.path = data.path;
    menuForm.icon = data.icon;
    menuForm.sort = data.sort;
    menuForm.name = data.name;
    menuForm.action = data.action;
    menuForm.method = data.method;
    /* 判断是 目录，菜单，按钮 */
    handleJudgeMenuType();
  } else {
    /* 新增 */
    methodType.value = "POST";

    menuForm.type = 1;
    menuForm.path = "";
    menuForm.method = "";
    menuForm.action = "";
    menuForm.icon = "";
    menuForm.sort = 0;
    menuForm.name = "";
  }
};
/* 数据初始化 */
const handleInitData = () => {
  methodType.value = "POST";
  menuForm.title = "";
  menuForm.p_id = 0;
  menuForm.type = 1;
  menuForm.path = "";
  menuForm.method = "";
  menuForm.action = "";
  menuForm.icon = "";
  menuForm.sort = 0;
  menuForm.name = "";
};
/* 判断是 目录，菜单，按钮 */
const handleJudgeMenuType = () => {
  if (!["", null].includes(menuForm.name)) {
    menuForm.type = 2;
    rules.value = menuRules;
    return;
  }
  if (!["", null].includes(menuForm.action)) {
    menuForm.type = 3;
    rules.value = buttonRules;
    return;
  }
  /* 默认目录 */
  menuForm.type = 1;
  rules.value = contentRules;
  formRef.value?.clearValidate();
};
/* 添加节点 */
const handleAppend = (node: Node, data: IMenuDTO) => {
  if (!node.loaded) {
    ElMessage.warning(`请先点击左侧小箭头，加载下级，再进行新增下级操作`);
    return;
  }
  isParent.value = false;
  /* 判断是否有未保存过的子节点，如果有，则不允许再添加，只允许有一条未保存过的子节点 */
  const childNodes = node.childNodes;
  for (let i = 0; i < childNodes.length; i++) {
    if (childNodes[i].data.id === -1) return;
  }
  const newChild: IMenuDTO = {
    id: -1,
    title: "",
    action: null,
    icon: null,
    method: "",
    name: "",
    p_id: data.id,
    path: "",
    sort: null,
    type: 1,
    items: []
  };

  if (!data.items) {
    data.items = [];
  }
  /* TODO:感觉是源码的问题，先过滤得到id不为-1的数据 */
  data.items = data.items.filter((item: IMenuDTO) => item.id !== -1);
  data.items.push(newChild);

  node_had.value = node;
  handleInitData();
  menuForm.p_id = node.data.id;
};
/* 删除节点 */
const handleRemove = (node: Node, data: IMenuDTO) => {
  isParent.value = true;
  if (data.id == -1) {
    const parent = node.parent;
    const items = parent.data.items || parent.data;
    const index = items.findIndex((d: IMenuDTO) => d.id === data.id);
    items.splice(index, 1);
    node.parent.loaded = false;
    node.parent.loadData(() => {});
    handleInitData();
  } else {
    id.value = data.id;
    /* 发送请求id 去删除数据 */
    delVisibleType.value = "delete";
    node_had.value = node;
    deleteMessageBox();
  }
};
/* 切换菜单类型 */
const handleChangeMenuType = (data: string | number | boolean | undefined) => {
  menuForm.type = data as 1 | 2 | 3;
  if (data === 1) {
    rules.value = contentRules;
    menuForm.method = "";
    menuForm.action = "";
    menuForm.name = "";
  } else if (data === 2) {
    rules.value = menuRules;
    menuForm.method = "";
    menuForm.action = "";
  } else if (data === 3) {
    rules.value = buttonRules;
    menuForm.icon = "";
    menuForm.name = "";
  }
  formRef.value?.clearValidate();
};

/* 加载节点数据 */
const loadNode = async (node: Node, resolve: (data: IMenuDTO[]) => void) => {
  node_had.value = node;
  if (node.level === 0) {
    const data: IMenuDTO = {
      id: 0 /* 这里注意需要取0，根节点id为0 */,
      title: "菜单信息管理",
      action: null,
      icon: null,
      method: "",
      name: "",
      p_id: 0,
      path: "",
      sort: null,
      type: 1
    };
    return resolve([data]);
  }
  if (node.data.id === "") return resolve([]);
  try {
    searchCondition.p_id = node.data.id;
    const res = await getMenuInfo<Array<IMenuDTO>, ISearchMenu>(searchCondition);
    if (res.status === 1 && res.result.length !== 0) {
      return resolve(res.result);
    }
    return resolve([]);
  } catch (error) {
    console.log(error);
    return resolve([]);
  }
};
/* 保存或编辑 */
const submitForm = () => {
  if (isParent.value && node_had.value?.data && node_had.value.data.id === 0) {
    ElMessage.warning(`'菜单信息管理'目录不能修改`);
    return;
  }

  if (!formRef.value) return;
  formRef.value.validate(valid => {
    if (!valid) {
      ElMessage.warning("请填写必填字段");
      return;
    }
    submitFormInfo();
  });
};
/* 保存或编辑信息 */
const submitFormInfo = () => {
  /* 防止多次提交 */
  disabledbtn.value = true;
  loading.value = true;
  commonMenuInfo(menuForm, methodType.value)
    .then(res => {
      ElMessage.success(res.msg);
      /* 重新刷新数据 */
      // this[refreshMethod]();
      handleUpdateTree();
      handleInitData();
    })
    .catch(() => {})
    .finally(() => {
      disabledbtn.value = false;
      loading.value = false;
    });
};
/* 打开删除弹框 */
const deleteMessageBox = () => {
  ElMessageBox.confirm("删除不可恢复，是否确定删除?", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(() => {
      deleteInfo([id.value]);
    })
    .catch(() => {
      ElMessage.info("已取消删除");
    });
};

/* 删除后的信息 */
const deleteInfo = (idArray: Array<number>) => {
  disabledbtn.value = true;
  deleteMenuInfo({ idArray })
    .then(() => {
      handleUpdateTree();
      handleInitData();
      ElMessage.success(`删除数据成功`);
    })
    .catch(() => {})
    .finally(() => {
      disabledbtn.value = false;
    });
};

/* 监听筛选数据 */
watch(filterText, val => {
  treeRef.value?.filter(val);
});
rules.value = contentRules;
/* 获取请求方式 */
getDictData("REQUEST_METHOD", selectRequestMethodList);
</script>

<style scoped>
.el-row {
  margin-bottom: 15px;
}

.el-col {
  border-radius: 4px;
}

.bg-purple-dark {
  background: #99a9bf;
}

.bg-purple {
  background: #d3dce6;
}

.bg-purple-light {
  background: #e5e9f2;
}

.grid-content {
  border-radius: 4px;
  min-height: 36px;
}

.row-bg {
  padding: 10px 0;
  background-color: #f9fafc;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}

/* 提示图标设置 */
.icon-wzg-config {
  height: 30px;
  line-height: 30px;
}

.el-tree {
  height: 740px;
  overflow: scroll;
}

.red {
  color: #f00;
}

/* 修改select的盒模型 */
.el-select {
  display: block;
}

:deep(.el-tree-node__label) {
  width: 100%;
}

.ml0 {
  margin-left: 0;
}
</style>
